﻿namespace SenenFernandez.SmartExtensionMethods
{
    using Enum;
    using System;
    using System.Diagnostics;
    using System.Text;
    using System.Windows.Interop;

    /// <summary>
    /// Native Window methods class.
    /// </summary>
    public static class NativeWindow
    {
        /// <summary>
        /// Gets the title of a window by its handle.
        /// </summary>
        public static string GetWindowTitle(this IntPtr handle)
        {
            int windowTextLength = handle.GetWindowTextLength();
            var stringBuilder = new StringBuilder(windowTextLength + 1);
            handle.GetWindowText(stringBuilder, stringBuilder.Capacity);
            return stringBuilder.ToString();
        }

        /// <summary>
        /// Sets window on focus.
        /// </summary>
        public static void RestoreWindow(this IntPtr handle)
        {
            if (handle != IntPtr.Zero)
            {
                if (handle.IsIconic())
                {
                    handle.ShowWindow(ShowStyle.Restore);
                }
                handle.SetForegroundWindow();
            }
        }

        /// <summary>
        /// Sets window on focus.
        /// </summary>
        public static void RestoreWindow(this System.Windows.Window window)
        {
            window.Show();
            new WindowInteropHelper(window).Handle.RestoreWindow();
        }

        /// <summary>
        /// Removes all window borders and titles, leaving only the content.
        /// </summary>
        public static void SetWindowStyle(this IntPtr handle)
        {
            if (handle != IntPtr.Zero)
            {
                var style = handle.GetWindowLong(WindowIndex.Style);
                style &= ~(WindowStyle.Minimize
                           | WindowStyle.Maximize
                           | WindowStyle.Border
                           | WindowStyle.DlgFrame
                           | WindowStyle.SysMenu
                           | WindowStyle.ThickFrame
                    );
                handle.SetWindowLong(WindowIndex.Style, style);
                var additionalStyle = handle.GetWindowLong(WindowIndex.ExtendedStyle);
                additionalStyle &= ~(WindowStyle.Group | WindowStyle.ExDlgModalFrame | WindowStyle.ExClientEdge);
                handle.SetWindowLong(WindowIndex.ExtendedStyle, additionalStyle);
                handle.SetWindowPos(0, 0, 0, 0, 0, PositionFlags.NoSize
                                                   | PositionFlags.NoMove
                                                   | PositionFlags.NoZorder
                                                   | PositionFlags.NoOwnerZorder
                                                   | PositionFlags.FrameChanged
                    );
            }
        }

        /// <summary>
        /// Removes window's title bar
        /// </summary>
        public static void SetWindowTitleStyle(this IntPtr handle, bool visible)
        {
            if (handle != IntPtr.Zero)
            {
                Rectangle rect;
                if (handle.GetWindowRect(out rect))
                {
                    handle.SetWindowTitleStyle(visible, rect.Left, rect.Top, rect.Width, rect.Height);
                }
            }
        }

        /// <summary>
        /// Removes window's title bar
        /// </summary>
        public static void SetWindowTitleStyle(this IntPtr handle, bool visible, int originX, int originY, int windowWidth, int windowHeight)
        {
            if (handle != IntPtr.Zero)
            {
                var windowLong = handle.GetWindowLong(WindowIndex.Style);
                handle.SetWindowLong(WindowIndex.Style,
                    visible
                        ? (windowLong | WindowStyle.Caption)
                        : (windowLong & ~(WindowStyle.Border | WindowStyle.DlgFrame)));
                handle.SetWindowPos(0, originX, originY, windowWidth, windowHeight, PositionFlags.FrameChanged);
            }
        }

        /// <summary>
        /// Set window decoration.
        /// </summary>
        public static void SetDecoration(this IntPtr handle, System.Windows.Rect workingArea)
        {
            SetDecoration(handle,
                (int) workingArea.Left,
                (int) workingArea.Top,
                (int) workingArea.Width,
                (int) workingArea.Height);
        }

        /// <summary>
        /// Set window decoration.
        /// </summary>
        public static void SetDecoration(this IntPtr handle, double left, double top, double width, double height)
        {
            if (handle != IntPtr.Zero)
            {
                SetWindowStyle(handle);
                SetWindowTitleStyle(handle, false, (int) left, (int) top, (int) width, (int) height);
                RestoreWindow(handle);
            }
        }

        /// <summary>
        /// Get Window ProductVersion.
        /// </summary>
        public static string GetWindowVersion(this IntPtr handle)
        {
            var result = string.Empty;
            IntPtr processId;
            handle.GetWindowThreadProcessId(out processId);
            var process = Process.GetProcessById(processId.ToInt32());
            result = process.MainModule.FileVersionInfo.ProductVersion;
            return result;
        }
    }
}